# -*- coding: utf-8 -*-
import os.path
import pickle
import codecs
import urllib2
import os
import datetime

from kivy.core.window import Window
from kivy.lang import Builder
from kivy.logger import Logger

from model.gamestate import GameState, Phase
from model.syssettings import SysSettings
from model.json_rounds_creater import JsonRoundsCreater
from platform_adapter import PlatformAdapter
from model.explanatory_dictionary import ExplanatoryDictionary
from constants import STATISTIC_COUNT
from constants import EXPORT_PROTOCOL_VERSION
from ui.sound_manager import SoundManager, Sounds

JSON_EXT = ".json"
PKL_EXT = ".pkl"
GAME_PREFIX = EXPORT_PROTOCOL_VERSION + "_game"
STATISTIC_DIR = "statistics"


def stat_files_list():
    """ Returns list of all names of json files without extension
    """
    return [file_name[:-len(JSON_EXT)]
            for file_name in os.listdir(STATISTIC_DIR)
            if file_name.endswith(JSON_EXT)]


def full_json_filename(fname):
    """ Returns full name of json file
    """
    return os.path.join(STATISTIC_DIR, fname + JSON_EXT)


def json_by_filename(fname):
    """ Returns json string by full file name
    """
    with codecs.open(fname, encoding='utf-8', mode='r') as f:
        return f.read()


def _creation_time(stat_file):
    return int(os.stat(full_json_filename(stat_file)).st_ctime)


def parse_id_from_filename(fname):
    """ Returns json file id by filename
    """
    return int(fname[len(GAME_PREFIX):])


def parse_version_from_filename(fname):
    """ Returns json file version by filename
    """
    return fname[:len(EXPORT_PROTOCOL_VERSION)]


def _try_to_send_old_stat(json_sender, server_name):
    """ Send all json files if has connection
    """
    stfiles = stat_files_list()
    to_remove_count = len(stfiles)-STATISTIC_COUNT
    for i in xrange(to_remove_count):
        os.remove(full_json_filename(stfiles[i]))
    for fname in stat_files_list():
        json_file = full_json_filename(fname)
        if parse_version_from_filename(fname) == EXPORT_PROTOCOL_VERSION:
            json_string = json_by_filename(json_file)
            json_sender.dump_to_url(server_name +
                                    '/create_game_history',
                                    json_string, json_file, True)


class BasePresenter(object):

    def request_app_close(self):
        pass

    def close_app(self):
        """ Saving gamestate to pickled file before close app
        """
        self.game_state.is_paused = True
        Logger.debug('Save game_state: ')
        Logger.debug('To file: data/pickled_gamestate.pkl')
        Logger.debug('Current phase: ' + str(self.game_state.phase))

        pickled_file = open('data/pickled_gamestate.pkl', 'wb')

        pickle.dump(self.game_state, pickled_file)
        pickled_file.close()
        return True

    def resume_app(self):
        """ Resume gamestate from pickled file
        """
        if os.path.exists('data/pickled_gamestate.pkl'):
            Logger.debug(
                'Load game_state from file: data/pickled_gamestate.pkl')
            pickled_file = open('data/pickled_gamestate.pkl', 'rb')

            self.game_state = pickle.load(pickled_file)
            Logger.debug('game_state loaded: ')
            Logger.debug('phase in loaded game_state: ' +
                         str(self.game_state.phase))
            pickled_file.close()
            if self.game_state.phase in [Phase.GUESS_WORD, Phase.COUNTDOWN]:
                self.change_phase(Phase.FROM_TO)
            else:
                self.change_phase(self.game_state.phase)

    def save_statistics(self):
        """ Send all json files in statistics folder and json from this game
        """
        self.game_state.is_paused = True  # nobody knows what this line does

        json_creater = JsonRoundsCreater()
        json_string = json_creater.create_json_rounds(self.game_state)
        now = datetime.datetime.now()
        time_stamp = now.strftime('%m.%d_%H.%M.%S')
        file_name = os.path.join('statistics', '{}{}.json'.format(GAME_PREFIX,
                                                                  time_stamp))
        try:
            with codecs.open(file_name, encoding='utf-8',
                             mode='w') as f:
                f.write(json_string)
        except:
            Logger.debug('Error while saving file {}'.format(self.file_name))
        _try_to_send_old_stat(json_creater, self.settings.game.server_name)


class Presenter(BasePresenter):
    orientation_change_enabled = True
    registered_kvs = {}

    def __init__(self, main_view, path):
        self.path = path
        self.settings = SysSettings(self.path + '/data/config.ini')
        _try_to_send_old_stat(JsonRoundsCreater(),
                              self.settings.game.server_name)
        self.adapter = PlatformAdapter.get_adapter()
        self.sound_manager = SoundManager()
        self.sound_manager.configure(self.settings)

        self.widgets = dict()
        self.explanatory_dictionary = ExplanatoryDictionary()
        self.main_view = main_view
        self.game_state = GameState(None, None, None, None, None, None, None)
        self.num_pad = None

        Builder.load_file(os.path.join(os.path.dirname(__file__),
                                       'hatwidget.kv'))
        Builder.load_file(os.path.join(os.path.dirname(__file__),
                                       'results_general.kv'))

    def change_phase(self, phase):
        """ Changes phase of application

        Args:
        phase: (Phase)

        """
        if self.num_pad is not None:
            self.num_pad.dismiss()
        self.adapter.hide_keyboard()
        self.main_view.content.clear_widgets()
        self.game_state.phase = phase
        w = self.widgets[phase](self.game_state, self)
        self.main_view.content.add_widget(w)

        self.rotate()

    def orientation(self):
        return Window.rotation

    def register_view(self, phase, widget_class, widget_names):
        """ Adds screen to presenter's dictionary

        Args:
        phase: (Phase)
        widget: (class)
        widget_name: (String)

        """
        if phase in self.widgets:
            raise Exception('Duplicate widget for phase %s' % phase)
        if widget_names is not None:
            for widget_name in widget_names:
                if widget_name in self.registered_kvs:
                    raise Exception('Trying to load duplicate %s.kv' %
                                    widget_name)
                self.registered_kvs[widget_name] = phase
                Builder.load_file(os.path.join(os.path.dirname(__file__),
                                               widget_name + '.kv'))
        self.widgets[phase] = widget_class

    def restart(self):
        self.save_statistics()
        self.game_state.clear()
        self.change_phase(Phase.WELCOME)

    def rotate(self):
        phase = self.game_state.phase
        if phase in [Phase.FROM_TO, Phase.COUNTDOWN,
                     Phase.GUESS_WORD, Phase.RESULTS_OF_ONE_PAIR]:
            orientation = self.settings.graphics.horizontal_orientation
        else:
            orientation = self.settings.graphics.vertical_orientation
        self.set_orientation(orientation)

    def set_orientation(self, orietation):
        if self.orientation_change_enabled:
            Window.rotation = orietation

    def update(self):
        for widget in self.main_view.content.children:
            widget.update()
